# -*- coding: utf-8 -*-

#    Copyright (C) 2014 by Promotux
#                        di Francesco Meloni snc - http://www.promotux.it/

#    Author: Francesco Meloni  <francesco@promotux.it>

#    This file is part of Promogest.

#    Promogest is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 2 of the License, or
#    (at your option) any later version.

#    Promogest is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.

#    You should have received a copy of the GNU General Public License
#    along with Promogest.  If not, see <http://www.gnu.org/licenses/>.

import urllib2
import urllib
import collections
import csv
import itertools
import base64
import hashlib
import datetime
import Environment
from web_lib.page import Page, expose, Response, change_schema
import json
from dao.Ente import Ente
import datetime
from lib.utils import prep2json, dateToString
from webEnv import *
from web_lib.webutils import leggiInSessione
import ckanapi

@expose('/pg/ac_Rilevazioni/<action>')
@expose('/pg/ac_Rilevazioni')
def rilevazioni(req, action=None):
    """
    Una delle parti più importanti. Il collect serve se questa parte
    funziona bene.
    Qui vengono salvati e rielaborati i dati.
    """
    def __show__(req, action=None):
        """ Semplice funzione di visualizzazione, da qui poi il jtable
        richiamerà  il vero e proprio list per l'elenco dei dati
        """
        if not leggiInSessione(sezione="Main", chiave="schema"):
            url_red = "/pg/main"
            return Page(req).redirect(url_red)
        pageData = {'file': "/pg/ac_Rilevazioni"}
        return Page(req).render(pageData)

    def __list__(req, action=None):
        """ Funzione di visualizzazione e filtraggio dei dati.
        """
        codice = req.args.get("Codice")
        fk_categoria = None
        fk_dadata = None
        fk_adata = None
        if codice and codice != "None" and codice != "":
            ente = Ente().select(codice=codice)
            if ente:
                Environment.census = True
                Environment.sch = ente[0].denominazione_breve.lower().replace(" ", "")
                change_schema(req, ente[0].denominazione_breve.lower().replace(" ", ""))
                fk_ente = ente[0].id
                fk_categoria = req.args.get("fk_id_categoria")
                fk_dadata = req.args.get("fk_dadata")
                fk_adata = req.args.get("fk_adata")
            else:
                return Response("{}")
        else:
            fk_ente = req.form.get("fk_id_ente")
            fk_categoria = req.form.get("fk_id_categoria")
            fk_dadata = req.form.get("fk_dadata")
            fk_adata = req.form.get("fk_adata")
        sorting = req.args.get("jtSorting")
        offset = req.args.get("jtStartIndex")
        batchSize = req.args.get("jtPageSize")

        from dao.Categoria import Categoria
        from dao.CategoriaCampo import CategoriaCampo
        from dao.OpenData import OpenData
        from dao.EnteCategoria import EnteCategoria
        from dao.Campo import Campo
        from dao.ParametriExport import ParametriExport
        from dao.Esportazione import Esportazione


        daos = OpenData().select(
                            batchSize=batchSize,
                            id_categoria=fk_categoria,
                            id_ente=fk_ente,
                            daData = fk_dadata,
                            aData = fk_adata,
                            offset=offset,
                            orderBy=sorting)
        count = OpenData().count(
                            id_categoria=fk_categoria,
                            id_ente=fk_ente,
                            daData = fk_dadata,
                            aData = fk_adata,
                            batchSize=None)
        daoss = daos[:]
        for d in daoss:
            if Esportazione().select(id_opendatastore= d.id):
                setattr(d,"esported","SI")
            else:
                setattr(d,"esported","NO")
            objs = json.loads(d.objson)
            lissta = []
            for ob in objs:
                for k in ob:
                    ca = Campo().select(denominazione=k)
                    if ca and ca[0].tipo_campo in ["img","firm"]:
                        ob[k] = ""
                lissta.append(ob)
            d.objson = lissta
        item = {
            "Result":"OK",
            "TotalRecordCount": count,
            "Records": prep2json(daoss)
            }
        jasoned = json.dumps(item)
        Environment.census = False
        Environment.sch = None
        return Response(jasoned)

    def __edit__(req, action=None):
        """ funzione di modifica della rilevazione
        """
        from dao.Categoria import Categoria
        from dao.CategoriaCampo import CategoriaCampo
        from dao.OpenData import OpenData
        from dao.EnteCategoria import EnteCategoria
        from dao.Operatore import Operatore
        id = req.form.get("id")
        if id:
            d = OpenData().getRecord(id=int(id))
        else:
            d = OpenData()
        categorie = Categoria().select(batchSize=None, orderBy="denominazione")
        enti = []
        # Gestione Per schema, ha aggiunto complessità  ma permette
        #di rendere il db piÃ¹ gestibile nel medio periodo
        if leggiInSessione(req, sezione="Main", chiave="schema"):
            enti = Ente().select(denominazione_breve=leggiInSessione(req, sezione="Main", chiave="schema"),orderBy="denominazione", batchSize=None)
        else:
            url_red = "/pg/ac_Rilevazioni"
            return Page(req).redirect(url_red)
        if not enti:
            enti = Ente().select(batchSize=None,orderBy="denominazione")
        #print "DDDD", d.__dict__
        operatori = []
        for e in enti:
            operatori.append(Operatore().select(batchSize=None))

        pageData = {'file': "pg/addedit/ae_rilevazione",
                    "dao": d,
                    "categorie": categorie,
                    "enti":enti,
                    "operatori":[item for sublist in operatori for item in sublist]
                    }
        return Page(req).render(pageData)


    def __create__update__(req, action=None):
        """Aggiunge una riga alle rilevazioni"""
        from dao.Categoria import Categoria
        from dao.CategoriaCampo import CategoriaCampo
        from dao.OpenData import OpenData
        from dao.EnteCategoria import EnteCategoria
        id = req.form.get("id")
        from werkzeug.formparser import FormDataParser
        url_red = "/pg/ac_Rilevazioni"
        if id != "None":
            d = OpenData().getRecord(id=int(id))
            obbj = json.loads(d.objson)[0]
        else:
            d = OpenData()
            d.data_inserimento = datetime.datetime.now()
        tai = CategoriaCampo().select(id_categoria=int(req.form.get("id_categoria")),orderBy="ordine", batchSize=None)
        campi = [x.campo for x in tai]
        d.id_ente = int(req.form.get("id_ente"))
        d.id_categoria = int(req.form.get("id_categoria"))
        d.id_operatore = int(req.form.get("id_operatore"))
        categoria = Categoria().getRecord(id= int(req.form.get("id_categoria")))
        if not categoria:
            return Page(req).redirect(url_red)
        ente = Ente().getRecord(id= int(req.form.get("id_ente")))
        if not ente:
            return Page(req).redirect(url_red)
        dd = {}
        for c in campi:
            if c.tipo_campo.lower() in "img" or c.tipo_campo.lower() in "firm":
                if c.denominazione in req.files:
                    f = req.files[c.denominazione]
                    #name = f.filename
                    data = f.read()
                    if data:
                        dd[c.denominazione] = base64.b64encode(data)
                    else:
                        if c.denominazione in obbj:
                            dd[c.denominazione] = obbj[c.denominazione]
                else:
                    dd[c.denominazione] = ""
            else:
                dd[c.denominazione] = req.form.get(c.denominazione.encode("utf8"))
            dd["id_"+c.denominazione] = c.id
        dd["id_categoria"] = int(req.form.get("id_categoria"))
        dd["Categoria"] = categoria.denominazione
        dd["Ente"]= ente.denominazione
        d.objson = json.dumps([dd], ensure_ascii=False, encoding='utf8')
        has_record = hashlib.sha224(str(d.objson)).hexdigest()
        odd = OpenData().select(hash_record = has_record, batchSize=None)
        if not odd:
            d.hash_record = has_record
        d.persist()
        url_red = "/pg/ac_Rilevazioni"
        return Page(req).redirect(url_red)

    def __delete__(req, action=None):
        """Cancella una riga"""
        from dao.Categoria import Categoria
        from dao.CategoriaCampo import CategoriaCampo
        from dao.OpenData import OpenData
        from dao.EnteCategoria import EnteCategoria
        id = int(req.form.get("id"))
        d = OpenData().getRecord(id=id)
        try:
            d.delete()
            item = {"Result": "OK", }
        except:
            item = {
                "Result":"ERROR",
                "Message": "Cancellazione riga non riuscita"}
        jasoned = json.dumps(item, ensure_ascii=False, encoding='utf8')
        return Response(jasoned)

    def __multi_delete__(req, action=None):
        rilev = req.form.get("rilev")
        dd =  eval(json.dumps(rilev)).replace('"',"")
        from dao.OpenData import OpenData
        for a in eval(dd):
            d = OpenData().getRecord(id=int(a))
            try:
                d.delete()
                item = {"Result": "OK", }
            except:
                item = {
                    "Result":"ERROR",
                    "Message": "Cancellazione riga non riuscita"}
        url_red = "/pg/ac_Rilevazioni"
        return Page(req).redirect(url_red)

    def __get_cate__(req, action=None, tipo=None):
        """ DAto un ente resituisce quali siano le categorie a lui assegnate per riempire
        la combo """
        from dao.Categoria import Categoria
        from dao.CategoriaCampo import CategoriaCampo
        from dao.OpenData import OpenData
        from dao.EnteCategoria import EnteCategoria
        idEnte = req.args.get("id_ente")
        if not idEnte:
            idEnte =  Ente().select(denominazione_breve=leggiInSessione(req,sezione="Main", chiave="schema"))[0].id
        tai = Ente().getRecord(id=idEnte)
        if tai:
            item = [a.categoria for a in EnteCategoria().select(id_ente=tai.id)]
        else:
            item = []
        jasoned = json.dumps(prep2json(item), ensure_ascii=False, encoding='utf8')
        return Response(jasoned)

    def __get_dao_cate__(req, action=None):
        from dao.Categoria import Categoria
        from dao.CategoriaCampo import CategoriaCampo
        from dao.OpenData import OpenData
        from dao.EnteCategoria import EnteCategoria
        idCategoria = req.args.get("id_categoria")
        tai = Categoria().getRecord(id=idCategoria)
        jasoned = json.dumps(prep2json(tai), ensure_ascii=False, encoding='utf8')
        return Response(jasoned)


    def __preview__(req, action=None):
        """ Gestione della Get per odcensu e del post interno di odcollect
        """
        codice = req.args.get("Codice")
        if codice and codice != "None" and codice != "":
            ente = Ente().select(codice=codice)
            if ente:
                Environment.census = True
                Environment.sch = ente[0].denominazione_breve.lower().replace(" ", "")
                change_schema(req, ente[0].denominazione_breve.lower().replace(" ", ""))
        from dao.Categoria import Categoria
        from dao.CategoriaCampo import CategoriaCampo
        from dao.OpenData import OpenData
        from dao.EnteCategoria import EnteCategoria
        from dao.Campo import Campo
        id = req.args.get("id")
        get = True
        if not id and id != "" and id !="None":
            id = req.form.get("id")
            get = False
        if not id:
            url_red = "/pg/ac_Rilevazioni"
            return Page(req).redirect(url_red)

        d = OpenData().getRecord(id=int(id))
        ca =  Categoria().getRecord(id=d.id_categoria)
        djson = json.loads(d.objson)
        campdict = {}
        tai = CategoriaCampo().select(id_categoria=d.id_categoria,orderBy="ordine", batchSize=None)
        idcampi = [dd.id_campo for dd in tai]
        campi = Campo().select(idCampo=idcampi, batchSize=None)
        for c in Campo().select(batchSize=None):
            campdict[c.denominazione] = c.tipo_campo
        pp = req.args.get("pp")
        if get and pp !="1":
            item = prep2json(d),
            jasoned = json.dumps(item,sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False, encoding='utf8')
            #print "jasoned", jasoned
            Environment.census = False
            Environment.sch = None
            return Response(jasoned)

        else:
            # questa Ã¨ la parte in cui gestiamo l'anteprima locale
            markers = []
            x,y = __get_coords__(d)

            tipoGeo = ca.tipo_geo
            paths = []
            if x and y:
                try:
                    for g in xrange(len(eval(x[0]))):
                        altronome = {}
                        altronome["latLng"] = [list((eval(x[0])))[g],list((eval(y[0])))[g]]
                        altronome["data"] = "BOH"+str(g)
                        markers.append(altronome)
                except:
                        altronome = {}
                        altronome["latLng"] = [str(x[0]), str(y[0])]
                        altronome["data"] = "BOH"
                        markers.append(altronome)
                if tipoGeo == "Posizione":
                    tippo = None
                    #print "POSIZIONE", x,y
                elif tipoGeo == "Area":
                    tippo = "polygon"
                    paths = [list(q) for q in zip(eval(x[0]), eval(y[0]))]
                    paths = paths + [paths[0]]
                    markers = [markers[0]]
                    #print "AREA", x,y
                elif tipoGeo == "Percorso":
                    tippo = "polyline"
                    paths = [list(q) for q in zip(eval(x[0]), eval(y[0]))]
                    markers = [markers[0],markers[-1]]
                    #print " PERCORSO", x,y
                elif tipoGeo == "Altitudine":
                    tippo = None
                    print "ALTITUDINE",x,y
                center = markers[0]["latLng"]
                icona = ca.icona_categoria
            else:
                icona = None
                paths = None
                tippo = None
                center = None
                marker = None
            pageData = {
                    'file': "/pg/dettaglio_rilevazione",
                    "dao": d,
                    "djson":djson,
                    "campi":campi,
                    "campdict":campdict,
                    "marker":markers,
                    "center": center,
                    "tippo":tippo,
                    "paths" :paths,
                    "icona_categoria":icona,
                    "pp":pp,
                    }
            return Page(req).render(pageData)

    def __ordina__(req, action=None):
        from dao.Categoria import Categoria
        daos = Categoria().select(batchSize=None)
        pageData = {'file': "pg/addedit/ae_opendata_ordina",
                    "daos": daos,
                    }
        return Page(req).render(pageData)

    def __ordina_salva__(req, action=None):
        #print "VEDIAMO", req.form.to_dict()
        try:
            ordine = eval(req.form.get("ordine"))
        except:
            ordine = []
        from dao.OpenData import OpenData
        for a in ordine:
            print "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", a
            d = OpenData().getRecord(id=a)
            d.ordine = ordine.index(a)
            d.persist()
        url_red = "/pg/ac_Rilevazioni"
        return Page(req).redirect(url_red)

    def __rilevazionidaordinare__(req):
        id_cat = req.form.get("id")
        if id_cat:
            from dao.OpenData import OpenData
            daos = OpenData().select(id_categoria=id_cat, batchSize=None, orderBy="ordine")
            pageData = {'file': "pg/rilevazioni_da_ordinare",
                        "daoss": daos,
                    }
            return Page(req).render(pageData)
        url_red = "/pg/ac_Rilevazioni/"
        return Page(req).redirect(url_red)

    def __export_param__(req, action=None):
        from exportToCkan import get_licenze_from_ckan
        print get_licenze_from_ckan()
        from exportToCkan import _export_param_
        return _export_param_(req, action=action)

    def __export__(req, action=None):
        print "AHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"
        from exportToCkan import _export_
        return _export_(req, action=action)

    def __import_csv_create__(req, action=None):
        from importCSVForCkan import _import_csv_create_
        return _import_csv_create_(req, action=action)

    def __import_csv_update__(req, action=None):
        from importCSVForCkan import _import_csv_update_
        return _import_csv_update_(req, action=action)


    def __json__(req, action=None):
        """ Gestione della Get per odcensu e del post interno di odcollect
        """
        codice = req.args.get("codice")
        if codice and codice != "None" and codice != "":
            ente = Ente().select(codice=codice)
            if ente:
                ente = ente[0]
                Environment.census = True
                Environment.sch = ente.denominazione_breve.lower().replace(" ", "")
                change_schema(req, ente.denominazione_breve.lower().replace(" ", ""))
            else:
                return Response("{}")

        else:
            return Response("{}")


        from dao.OpenData import OpenData
        id = req.args.get("id")
        if not id:
            return Response("{}")

        d = OpenData().getRecord(id=int(id))
        if not d:
            return Response("{}")
        item = prep2json(d)
        jasoned = json.dumps(item,sort_keys=True, indent=4, separators=(',', ': '), ensure_ascii=False, encoding='utf8')
        Environment.census = False
        Environment.sch = None
        return Response(jasoned)


    def __get_coords__(d):
        """ Questo è il formato json del necessario al plugin delle mappe jquery
                                                                                     """
        from dao.Categoria import Categoria
        from dao.CategoriaCampo import CategoriaCampo
        from dao.OpenData import OpenData
        from dao.EnteCategoria import EnteCategoria
        from dao.Campo import Campo
        from dao.TipoCampo import TipoCampo

        djson = json.loads(d.objson)
        tai = CategoriaCampo().select(id_categoria=d.id_categoria,orderBy="ordine", batchSize=None)
        idcampi = [d.id_campo for d in tai]
        geoxs = TipoCampo().select(denominazione="geox")
        if geoxs:
            geox = geoxs[0].id
        campoX = Campo().select(idCampo=idcampi, idTipo=geox, batchSize=None)
        x = []
        for a in campoX:
            x.append(djson[0][a.denominazione])
        geoys = TipoCampo().select(denominazione="geoy")
        if geoys:
            geoy = geoys[0].id
        campoY = Campo().select(idCampo=idcampi, idTipo=geoy, batchSize=None)
        y = []
        for aa in campoY:
            y.append(djson[0][aa.denominazione])
        return x,y

    #if Environment.schema is None:
        #url_red = "/pg/main"
        #return Page(req).redirect(url_red)
    if action=="List":
        return __list__ (req, action=action)
    elif action=="show":
        return __show__(req, action=action)
    elif action=="Create" or action == "Update":
        return __create__update__(req, action=action)
    elif action=="Delete":
        return __delete__(req, action=action)
    elif action == "Preview":
        return __preview__(req, action=action)
    elif action == "Edit":
        return __edit__(req, action=action)
    elif action == "ImportCsvCreate":
        return __import_csv_create__(req, action=action)
    elif action == "ExportParam":
        return __export_param__ (req, action=action)
    elif action == "ImportCsvUpdate":
        return __import_csv_update__(req, action=action)
    elif action == "GetCate":
        return __get_cate__(req, action=action)
    elif action == "MultiDelete":
        return __multi_delete__(req, action=action)
    elif action == "GetCoords":
        return __get_coords__(req, action=action)
    elif action == "GetDaoCate":
        return __get_dao_cate__(req, action=action)
    elif action == "export":
        return __export__(req, action=action)
    elif action == "Daojson":
        return __json__(req, action=action)
    elif action=="Ordina":
        return __ordina__(req, action=action)
    elif action=="OrdinaSalva":
        return __ordina_salva__(req, action=action)
    elif action=="rilevazionidaordinare":
        return __rilevazionidaordinare__(req)
    else:
        return __show__(req, action=action)
